package com.k.config;

import com.k.suess.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import javax.sql.DataSource;

/**
 * @program: SpringSecote01
 * @ClassName PassConfig
 * @description:配置密码对比策略
 * @author: xiaoJie
 * @create: 2024-09-11 20:01
 * @Version 1.0
 */
@Configuration
public class PassConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JdbcTokenRepositoryImpl jdbcTokenRepository;
    @Autowired
    private AccessDeniedHandler accessDeniedHandler;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置异常处理
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
        //配置会话失效设置
        http.sessionManagement(session ->{
            session.invalidSessionStrategy(new SessionScessConfig());
            session.maximumSessions(1).maxSessionsPreventsLogin(true);//设置会话并发机制  就是几个设备可以登
        });

        //配置退出设置
        http.logout()
                .logoutUrl("/out")
                        .logoutSuccessHandler(new LogoutConfig("/login"))
                .clearAuthentication(false)//清除认证缓存
                .invalidateHttpSession(false);//清除session

        //配置rememberMe 记住我权限  保存登录记录
        http.rememberMe()
                        .userDetailsService(userDetailsService)
                                .tokenRepository(jdbcTokenRepository)
                .rememberMeParameter("jizhu")
                .tokenValiditySeconds(3600*24*3);

        //配置视图修改
        http.formLogin()
                .loginPage("/login")//进入时哪个页面
            .loginProcessingUrl("/islogin")//发送什么请求到这个地方
            .successHandler(new MyForward("/ok"))
                .failureHandler(new MySuess("/no"));

        //配置拦截位置
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/favicon.ico").permitAll()
//                .antMatchers("/demo").denyAll()
//                .antMatchers("/demo").hasRole("admin")//配置角色  用户符合则通过
//                .antMatchers("/demo").hasAuthority("system:user:save")
//                .antMatchers("/ok").rememberMe()//记住我显示
//                .antMatchers("/ok").fullyAuthenticated()//不记住我显示
//                .antMatchers("/ok").access("@userMapper.selectById(1)")//access表达式
//                .antMatchers("/ok").access("isFullyAuthenticated()")
                //自定义校验权限
//                .antMatchers("/demo").access("@myServiceImpl.PermssionMenu(request,authentication)")
                .anyRequest().authenticated();
        //配置角色权限放行

//        //关闭csrf安全防护
//        http.csrf().disable();
    }

    //配置token表创建
    @Bean
    public JdbcTokenRepositoryImpl getTokenRepository(DataSource dataSource) {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
//        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;

    }


    //配置Session踢人下线
    @Bean
    public SessionRegistry sessionRegistry(){
        return new SessionRegistryImpl();
    }

    //配置密码判断策略
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
